
/**
\file
Defines the rainbow::draw_information class.
\author Sean Tromans
*/

#ifndef	RAINBOW_DRAW_INFORMATION_HPP
#define	RAINBOW_DRAW_INFORMATION_HPP

#include <rainbow/graphics_device/graphics_device.hpp>
#include <rainbow/exception/exception.hpp>

#include <sun/math/math.hpp>
#include <sun/lua/lua_fwd.hpp>

namespace rainbow
{

	/** Exception throw if two draw_information with different target devices are compared. */
	class different_device_targets_exception : public exception
	{
	public:
		different_device_targets_exception( )
			:	exception( "rainbow::different_device_targets_exception: Comparrison of draw_information objecs destined for different graphics_devices is invalid." )
		{}
	};

	/** Exception throw if an attempt is made to sort an invalid draw_information. */
	class invalid_draw_information_exception : public exception
	{
	public:
		invalid_draw_information_exception( )
			:	exception( "rainbow::invalid_draw_information_exception: Attempted use of invalid draw_information." )
		{}
	};

	/**
	Contains all the required information to draw a mesh to the viewport.
	\author Sean Tromans
	*/
	struct	draw_information
	{
		//
		//	Public Member Functions
		//
		public:

			/**
			Default Constructor.
			\author Sean Tromans
			*/
			draw_information( );

			/**
			Constructor.
			@param device The graphics device this draw_command is intended for.
			\author Sean Tromans
			*/
			draw_information( graphics_device & device );

			/**
			Determines whether the draw_command is valid.
			\author Sean Tromans
			*/
			bool is_valid( ) const;

		//
		//	Public Member Variables
		//	
		public:

			graphics_device * device;	///< The graphics device to be used when drawing this object.

			graphics_device::blend_handle	blend_handle;	///<	The handle to the blend_state to use when rendering this object.
			graphics_device::culling_handle	culling_handle;	///<	The handle to the culling_state to use when rendering this object.
			graphics_device::depth_handle	depth_handle;	///<	The handle to the depth_state to use when rendering this object.
			graphics_device::stencil_handle	stencil_handle;	///<	The handle to the stencil_state to use when rendering this object.

		//
		//	Static Member Functions
		//
		public:

			/**
			Exposes the draw_command to lua.
			@param L The Lua State being initialised.
			\author Sean Tromans.
			*/
			static void lua_interface( lua_State * L );

			/**
			Sorts by material settings.
			@param a The first draw_information to compare.
			@param b The first draw_information to compare.
			@returns true if a compares less than b. False otherwise.
			\author Sean Tromans
			*/
			static bool default_ordering( draw_information const & a, draw_information const & b );

			/**
			Tests whether the material settings for two draw_information objects are equal. Ignores mesh and positional information.
			@param a The first draw_information to compare.
			@param b The first draw_information to compare.
			@returns true if a's material is equal to b's. False otherwise.
			\author Sean Tromans
			*/
			static bool materials_equal( draw_information const & a, draw_information const & b );
	};

};

#endif	//RAINBOW_DRAW_INFORMATION_HPP
